`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    15:41:12 02/22/2011 
// Design Name: 
// Module Name:    csa_tree 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module csa_tree #(parameter N=8)(
    input [N-1:0] a_in,
    input [N-1:0] b_in,
    output [2*N-1:0] c_out
    );

	wire [N-1:0] partial[N-1:0];
	wire [N-1:0] sc[N-3:0], pss[N-3:0];
	
	genvar i;
	generate
		for(i=0; i<N; i=i+1) begin: csa_loop
			pp_calc #(.N(N)) partProd (a_in, b_in[i], partial[i][N-1:0]);
		end
	endgenerate

	assign c_out[0] = partial[0][0];
	CSA #(.N(N)) c1({1'b0, partial[0][N-1:1]},partial[1][N-1:0],{partial[2][N-2:0], 1'b0}, sc[0][N-1:0] ,{pss[0][N-2:0], c_out[1]}); 
	assign pss[0][N-1] = partial[2][N-1];//pss[0] ready for next csa mod
	
	//next 5 are identical with different numbers
	genvar j;
	generate
		for(j=1; j<=(N-3); j = j+1) begin: csa_loop2
			
			CSA #(.N(N)) c(pss[j-1][N-1:0], sc[j-1], {partial[j+2][N-2:0], 1'b0}, sc[j][N-1:0] ,{pss[j][N-2:0], c_out[j+1]});
			assign pss[j][N-1]=partial[j+2][N-1];
		end
	endgenerate
	
	//need to sum final results as for upper output bits
	NbitAdder #(.N(N)) result(pss[N-3][N-1:0], sc[N-3][N-1:0], 1'b0, c_out[(2*N)-2:N-1], c_out[2*N-1]);
	

endmodule
